#include <math.h>
#include <sstream>
#include <cstring>
#include "ArbitrarySectionTool.h"

using SG::DataStructure::Common::Real;

// 引入triangle库
#ifndef REAL
#define REAL Real
#endif

extern "C" { 
    #include "../ThirdLibrary/triangle.h"
}

using namespace std;
using SG::Algebra::Point;
using SG::FEMSolver::Element::Point2D;
using SG::FEMSolver::Element::Element;
using SG::FEMSolver::Element::Meshes;
using SG::FEMSolver::Element::ArbitrarySectionTool;
using SG::DataStructure::FEM::BeamSectionArbitrary;

// 匿名空间封装一些工具函数，将被在MeshT6中调用
namespace
{
    // 计算多边形内部点（用于标识孔洞）
    Point getPointInPolygon(const vector<Point>& polygon)
    {
        // 取顶点平均值作为内部点（算法有待改进，对于凹孔洞可能BUG）
        Real  y= 0.0, z = 0.0;
        for (const auto& pt : polygon)
        {
            y += pt.m_y;
            z += pt.m_z;
        }
        y /= polygon.size();
        z /= polygon.size();

        return Point{0.0, y, z};
    }

    // 计算网格尺寸
    Real calcAutoMeshSize(const vector<Point>& outerBoundary, 
                          const vector<vector<Point>>& innerHoles, 
                          Real densityFactor = 1000.0)
    {
        if (outerBoundary.size() < 3) return 0.0;

        // 计算外边界面积
        //工具匿名函数：利用鞋带公式（Shoelace Formula）计算平面封闭区域的面积
        auto calculateArea = [](const std::vector<SG::Algebra::Point>& poly) -> SG::DataStructure::Common::Real 
        {
            SG::DataStructure::Common::Real area = 0.0;
            size_t n = poly.size();
            for (size_t i = 0; i < n; ++i) {
                const auto& p1 = poly[i];
                const auto& p2 = poly[(i+1)%n];
                area += (p1.m_y * p2.m_z - p2.m_y * p1.m_z);
            }
            return fabs(area) * 0.5;
        };

        Real outerArea = calculateArea(outerBoundary);
        for (const auto& hole : innerHoles) 
        {
            if (hole.size() >= 3) outerArea -= calculateArea(hole);
        }
        return (outerArea / densityFactor);
    }

    // 初始化Triangle输入输出结构（整合内存分配逻辑，删除mallocTriangleMem依赖）
    void initTriangleio(struct triangulateio& in,
                        struct triangulateio& out,
                        const vector<Point>& outerBoundary,
                        const vector<vector<Point>>& innerHoles)
    {
        // 清零结构
        memset(&in, 0, sizeof(triangulateio));
        memset(&out, 0, sizeof(triangulateio));

        // 计算节点数、线段数、内孔数
        in.numberofpoints = outerBoundary.size();  // 外边界节点数
        for (const auto& hole : innerHoles) 
        {
            in.numberofpoints += hole.size();      // 累加内孔节点数
        }
        in.numberofsegments = in.numberofpoints;   // 封闭多边形：线段数 = 节点数
        in.numberofholes = 0;      // 内孔数量
        for (const auto& hole : innerHoles)
        {
            if (!hole.empty())  // 只统计非空的孔洞
            {
                in.numberofholes++;
            }
        }

        // 初始化Triangle输入结构基础字段
        in.numberofpointattributes = 0;    // 无节点属性
        in.numberoftriangleattributes = 0; // 无单元属性
        in.numberofregions = 0;            // 无区域属性
        in.pointattributelist = nullptr;   // 空属性列表
        in.regionlist = nullptr;           // 空区域列表
        in.pointmarkerlist = nullptr;
        in.segmentmarkerlist = nullptr;    // 不使用线段标记（原mallocTriangleio逻辑）

        // 内存分配（完全迁移mallocTriangleMem的内存分配逻辑，无遗漏）
        // 分配节点坐标内存（y/z二维）
        in.pointlist = nullptr;
        if (in.numberofpoints > 0) 
        {
            in.pointlist = new REAL[in.numberofpoints * 2];
        } 

        // 分配线段索引内存（每个线段2个节点）
        in.segmentlist = nullptr;
        if (in.numberofsegments > 0) 
        {
            in.segmentlist = new int[in.numberofsegments * 2];
        }

        // 分配内孔内部点内存（每个内孔1个点，y/z二维）
        in.holelist = nullptr;
        if (in.numberofholes > 0) 
        {
            in.holelist = new REAL[in.numberofholes * 2];
        } 


        // 初始化输出结构指针
        out.pointlist = nullptr;
        out.trianglelist = nullptr;
        out.segmentlist = nullptr;
        out.pointmarkerlist = nullptr;
        out.triangleattributelist = nullptr;
        out.neighborlist = nullptr;
        out.edgelist = nullptr;
        out.neighborlist = nullptr;    
        out.edgelist = nullptr;        
        out.edgemarkerlist = nullptr;  
        out.normlist = nullptr;        
    }

    // Triangle库输入
    void setTriangleInput(struct triangulateio* in,
                          const vector<Point>& outerBoundary,
                          const vector<vector<Point>>& innerHoles)
    {
        int index = 0;

        // 设置所有点坐标（外部边界 + 内部孔洞）
        for (const auto& pt : outerBoundary)
        {
            in->pointlist[index++] = pt.m_y;  
            in->pointlist[index++] = pt.m_z;  
        }

        for (const auto& hole : innerHoles)
        {
            for (const auto& pt : hole)
            {
                in->pointlist[index++] = pt.m_y;
                in->pointlist[index++] = pt.m_z;
            }
        }

        // 设置线段（闭合边界）
        int nodeNum = 0;  // triangle使用0基索引
        int beginNum = nodeNum;
        index = 0;

        // 外部边界线段
        for (size_t i = 0; i < outerBoundary.size(); ++i)
        {
            in->segmentlist[index++] = nodeNum;
            in->segmentlist[index++] = ++nodeNum;
        }
        in->segmentlist[index - 1] = beginNum;  // 闭合外部边界

        // 内部孔洞线段
        for (const auto& hole : innerHoles)
        {
            beginNum = nodeNum;
            for (size_t i = 0; i < hole.size(); ++i)
            {
                in->segmentlist[index++] = nodeNum;
                in->segmentlist[index++] = ++nodeNum;
            }
            in->segmentlist[index - 1] = beginNum;  // 闭合孔洞边界
        }

        // 设置孔洞内部点（用于标识孔洞区域）
        index = 0;
        for (const auto& hole : innerHoles)
        {
            if (hole.empty()) continue;
            Point innerPt = getPointInPolygon(hole);
            in->holelist[index++] = innerPt.m_y;
            in->holelist[index++] = innerPt.m_z;
        }
    }

    // 解析Triangle库输出
    void getTriangleOutput(struct triangulateio* out, _OUT Meshes& meshes)
    {
        // 读取节点
        meshes.nodes.reserve(out->numberofpoints); 
        for (int i = 0; i < out->numberofpoints; ++i)
        {
            // 从out->pointlist读取y/z坐标，nodeId从1开始
            meshes.nodes.emplace_back(Point2D{i + 1, out->pointlist[i * 2], out->pointlist[i * 2 + 1]});
        }    
        
        // 读取单元
        meshes.t6Elements.reserve(out->numberoftriangles);
        int currentEleId = 1;  // 单元ID从1开始
        for (int i = 0; i < out->numberoftriangles; ++i)
        {
            const std::vector<int> t6NodeIds = {out->trianglelist[i * 6] + 1,     out->trianglelist[i * 6 + 1] + 1, out->trianglelist[i * 6 + 2] + 1, 
                                                out->trianglelist[i * 6 + 5] + 1, out->trianglelist[i * 6 + 3] + 1, out->trianglelist[i * 6 + 4] + 1};
            meshes.t6Elements.emplace_back(Element{currentEleId++, t6NodeIds});
        }    
    }

    // 释放Triangle库内存
    void freeTriangleMem(struct triangulateio* in, struct triangulateio* out)
    {
        // 释放输入结构内存（new分配→delete[]释放）
        if (in != nullptr) 
        {
            if (in->pointlist != nullptr) 
            {
                delete[] in->pointlist;
                in->pointlist = nullptr;
            }

            if (in->segmentlist != nullptr) 
            {
                delete[] in->segmentlist;
                in->segmentlist = nullptr;
            }

            if (in->holelist != nullptr)
            {
                delete[] in->holelist;
                in->holelist = nullptr;
            }

            if (in->pointmarkerlist != nullptr) 
            {
                delete[] in->pointmarkerlist;
                in->pointmarkerlist = nullptr;
            }
        }

        // 释放输出结构内存
        if (out->pointlist != nullptr) 
        {
            trifree(out->pointlist);
            out->pointlist = nullptr;
        }

        if (out->trianglelist != nullptr)
        {
            trifree(out->trianglelist);
            out->trianglelist = nullptr;
        }

        if (out->segmentlist != nullptr) 
        {
            trifree(out->segmentlist);
            out->segmentlist = nullptr;
        }

        if (out->pointmarkerlist != nullptr) 
        {
            trifree(out->pointmarkerlist);
            out->pointmarkerlist = nullptr;
        }

        if (out->triangleattributelist != nullptr) 
        {
            trifree(out->triangleattributelist);
            out->triangleattributelist = nullptr;
        }

        if (out->neighborlist != nullptr) 
        {    
            trifree(out->neighborlist);
            out->neighborlist = nullptr;
        }

        if (out->edgelist != nullptr) 
        {
            trifree(out->edgelist);
            out->edgelist = nullptr;
        }

        if (out->edgemarkerlist != nullptr) 
        {
            trifree(out->edgemarkerlist);
            out->edgemarkerlist = nullptr;
        }

        if (out->normlist != nullptr) 
        {
            trifree(out->normlist);
            out->normlist = nullptr;
        }
    }

};


// T6网格生成实现（基于triangle库）
void ArbitrarySectionTool::MeshT6 (const BeamSectionArbitrary& profileData, _OUT Meshes& meshes)
{
    meshes.clear();

    const auto& outerBoundary = profileData.m_outer;
    const auto& innerHoles = profileData.m_holes;    

    // 初始化triangle输入输出结构
    struct triangulateio in, out;
    initTriangleio(in, out, outerBoundary, innerHoles); // 合并后的函数
    
    // 设置输入数据
    setTriangleInput(&in, outerBoundary, innerHoles);
    
    // 构造triangle命令参数
    const Real autoMeshSize = calcAutoMeshSize(outerBoundary, innerHoles, 1000.0); // 计算网格面积尺寸控制参数
    stringstream ss;
    ss << "pqzBo2Qa" << autoMeshSize;  // 添加尺寸控制
    const string argv = ss.str();

    // 调用triangle生成网格
    triangulate(const_cast<char*>(argv.c_str()), &in, &out, nullptr);

    // 解析输出结果
    getTriangleOutput(&out, _OUT meshes);

    // 释放资源
    freeTriangleMem(&in, &out);
}
